package cz.proks.easyhelpdesk.gwt.restapi;

import org.jsonmaker.gwt.client.Jsonizer;
import org.spiffyui.client.rest.RESTCallback;
import org.spiffyui.client.rest.RESTility;

import com.google.gwt.core.client.GWT;
import com.google.gwt.json.client.JSONValue;

import cz.proks.easyhelpdesk.api.config.Configuration;
import cz.proks.easyhelpdesk.api.model.base.AnIdentifiableModel;
import cz.proks.easyhelpdesk.api.model.base.Id;
import cz.proks.easyhelpdesk.api.model.base.IdJsonizer;
import cz.proks.easyhelpdesk.gwt.utils.JsonizerUtils;
import cz.proks.easyhelpdesk.gwt.utils.RestUtils;

public abstract class BaseRestApi<Domain extends AnIdentifiableModel> {
    
    public final static String GET_URL_PART = "/";
    public final static String CREATE_URL_PART = "/create";
    public final static String UPDATE_URL_PART = "/update";
    public final static String REMOVE_URL_PART = "/remove";    
    
    protected final static Jsonizer ID_JSONIZER = GWT.create(IdJsonizer.class);
    
    protected abstract String getBaseRestDomainUrlPart();
    
    protected abstract Jsonizer getDomainJsonizer();
    
    protected JSONValue domainToJson(Domain entity) {
        return JsonizerUtils.getJsonValue(getDomainJsonizer(), entity);
    }
    
    protected Domain jsonToDomain(JSONValue jsonValue) {
        return JsonizerUtils.getEntity(getDomainJsonizer(), jsonValue);
    }
        
    protected Id jsonIdentifierToIdentifier(JSONValue jsonValue) {
        return JsonizerUtils.getEntity(ID_JSONIZER, jsonValue);
    }
    
    protected final String getBaseDomainUrl() {
        return Configuration.WS.API_BASE_URL + getBaseRestDomainUrlPart();
    }
    
    protected final String getGetUrl() {
        return getBaseDomainUrl() + GET_URL_PART;
    }
    
    protected final String getCreateUrl() {
        return getBaseDomainUrl() + CREATE_URL_PART;
    }
    
    protected final String getUpdateUrl() {
        return getBaseDomainUrl() + UPDATE_URL_PART;
    }
    
    protected final String getRemoveUrl() {
        return getBaseDomainUrl() + REMOVE_URL_PART;
    }
    
    public void get(Long id, final DomainCallback<Domain> domainCallback) {
        RestUtils.makeRestRequest(getGetUrl() + id, new RestUtils.Callback(domainCallback) {
            
            @Override
            public void onSuccess(JSONValue val) {
                Domain domain = jsonToDomain(val);
                domainCallback.onDomainSuccess(domain);
            }                       
        });        
    }
    
    public void create(Domain entity, final IdCallback idCallback) {
        JSONValue jsonValue = domainToJson(entity);
        RestUtils.makeRestRequest(getCreateUrl(), jsonValue, RESTility.PUT, new RestUtils.Callback(idCallback) {
            
            @Override
            public void onSuccess(JSONValue val) {
                Id identifier = jsonIdentifierToIdentifier(val);
                idCallback.onIdSuccess(identifier);
            }                       
        });        
    }

    public void update(Domain entity, RESTCallback callback) {
        JSONValue jsonValue = domainToJson(entity);
        RestUtils.makeRestRequest(getUpdateUrl(), jsonValue, RESTility.POST, callback);        
    }

    public void remove(Long id, RestUtils.Callback callback) {
        RestUtils.makeRestRequest(getRemoveUrl() + "/" + id, null, RESTility.DELETE, callback);
    }    
}
